package br.com.mapagay.entidades.usuario;

import br.com.mapagay.conexao.Conexao;
import br.com.mapagay.entidades.Point;
import br.com.mapagay.entidades.Posicao;
import br.com.mapagay.exceptions.EntidadeNaoEncontrada;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Lauro
 */
public class Usuario extends Visitante implements Point {

    private String email;
    private String senha;
    private String nome;
    private String imagem;
    private Foto foto;
    private Endereco endereco;
    private Posicao posicao;
    private List<Usuario> amigos;

    public Usuario(Integer id) throws EntidadeNaoEncontrada {
        super(id);
        buscar();
    }

    public Usuario(String email, String senha) throws EntidadeNaoEncontrada {
        this.email = email;
        this.senha = senha;
        buscar(email, senha);
    }

    public Usuario(String email, String senha, String nome, String imagem) {
        this.email = email;
        this.senha = senha;
        this.nome = nome;
        this.imagem = imagem;
    }

    protected Usuario(Integer id, String email, String senha, String nome, String imagem) {
        super(id);
        this.email = email;
        this.senha = senha;
        this.nome = nome;
        this.imagem = imagem;
    }

    protected Usuario(Integer id, String email, String nome, String imagem) {
        super(id);
        this.email = email;
        this.nome = nome;
        this.imagem = imagem;
    }

    public static Usuario getUsuario(String email, String senha) throws EntidadeNaoEncontrada, SQLException {
        Connection conexao = Conexao.getConexao();
        try {
            String sql = getSQLBuscarPorEmailSenha();
            PreparedStatement query = conexao.prepareStatement(sql);
            query.setString(1, email);
            query.setString(2, senha);
            ResultSet result = query.executeQuery();
            if (result.next()) {
                Usuario usuario;
                if (result.getObject("admin.id") != null) {
                    usuario = new Administrador(result.getInt("u.id"),
                            result.getString("u.email"),
                            result.getString("u.nome"),
                            result.getString("u.imagem"));
                } else {
                    usuario = new Usuario(result.getInt("u.id"),
                            result.getString("u.email"),
                            result.getString("u.nome"),
                            result.getString("u.imagem"));
                }
                Conexao.close(conexao, query, result);
                return usuario;
            } else {
                Conexao.close(conexao, query, result);
                throw new EntidadeNaoEncontrada();
            }
        } catch (SQLException ex) {
            Conexao.close(conexao);
            throw ex;
        }
    }

    //<editor-fold defaultstate="expanded" desc="Metodos CRUD.">
    private boolean buscar() throws EntidadeNaoEncontrada {
        return buscar(null);
    }

    @Override
    protected boolean buscar(Connection conexao) throws EntidadeNaoEncontrada {
        boolean fecharConexao = conexao == null ? true : false;
        try {
            conexao = conexao == null ? Conexao.getConexao() : conexao;
            String sql = getSQLBuscarPorId();
            PreparedStatement query = conexao.prepareStatement(sql);
            query.setInt(1, this.getId());
            ResultSet result = query.executeQuery();
            if (result.next()) {
                this.setEmail(result.getString("u.email"));
                //this.setSenha(result.getString("senha"));
                this.setNome(result.getString("u.nome"));
                this.setImagem(result.getString("u.imagem"));
            } else {
                throw new EntidadeNaoEncontrada();
            }
            if (fecharConexao) {
                Conexao.close(conexao, query, result);
            }
            return true;
        } catch (SQLException ex) {
            if (fecharConexao) {
                Conexao.close(conexao);
            }
            return false;
        }
    }

    private boolean buscar(String email, String senha) throws EntidadeNaoEncontrada {
        return buscar(email, senha, null);
    }

    protected boolean buscar(String email, String senha, Connection conexao) throws EntidadeNaoEncontrada {
        boolean fecharConexao = conexao == null ? true : false;
        try {
            conexao = conexao == null ? Conexao.getConexao() : conexao;
            String sql = getSQLBuscarPorEmailSenha();
            PreparedStatement query = conexao.prepareStatement(sql);
            query.setString(1, this.getEmail());
            query.setString(2, this.getSenha());
            ResultSet result = query.executeQuery();
            if (result.next()) {
                this.setId(result.getInt("u.email"));
                //this.setSenha(result.getString("senha"));
                this.setNome(result.getString("u.nome"));
                this.setImagem(result.getString("u.imagem"));
            } else {
                throw new EntidadeNaoEncontrada();
            }
            if (fecharConexao) {
                Conexao.close(conexao, query, result);
            }
            return true;
        } catch (SQLException ex) {
            if (fecharConexao) {
                Conexao.close(conexao);
            }
            return false;
        }
    }

    @Override
    protected boolean inserir(Connection conexao) {
        boolean fecharConexao = conexao == null ? true : false;
        try {
            conexao = conexao == null ? Conexao.getConexao() : conexao;
            String sql = getSQLInsercao();
            PreparedStatement query = conexao.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            query.setString(1, this.getEmail());
            query.setString(2, this.getSenha());
            query.setString(3, this.getNome());
            query.setString(4, this.getImagem());
            query.executeUpdate();
            ResultSet result = query.getGeneratedKeys();
            result.first();
            int result_id = result.getInt(1);
            this.setId(result_id);
            if (fecharConexao) {
                Conexao.close(conexao, query, result);
            }
            return true;
        } catch (SQLException ex) {
            if (fecharConexao) {
                Conexao.close(conexao);
            }
            return false;
        }
    }

    @Override
    protected boolean atualizar(Connection conexao) {
        boolean fecharConexao = conexao == null ? true : false;
        try {
            conexao = conexao == null ? Conexao.getConexao() : conexao;
            String sql = getSQLAtualizacao();
            PreparedStatement query = conexao.prepareStatement(sql);
            query.setString(1, this.getEmail());
            query.setString(2, this.getSenha());
            query.setString(3, this.getNome());
            query.setString(4, this.getImagem());
            query.setInt(5, this.getId());
            query.executeUpdate();
            if (fecharConexao) {
                Conexao.close(conexao, query);
            }
            return true;
        } catch (SQLException ex) {
            if (fecharConexao) {
                Conexao.close(conexao);
            }
            return false;
        }
    }

    @Override
    protected boolean excluir(Connection conexao) {
        boolean fecharConexao = conexao == null ? true : false;
        try {
            conexao = conexao == null ? Conexao.getConexao() : conexao;
            String sql = getSQLExclusao();
            PreparedStatement query = conexao.prepareStatement(sql);
            query.setInt(1, this.getId());
            query.executeUpdate();
            if (fecharConexao) {
                Conexao.close(conexao, query);
            }
            return true;
        } catch (SQLException ex) {
            if (fecharConexao) {
                Conexao.close(conexao);
            }
            return false;
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Metodos Getters & Setters.">
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    @Override
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getImagem() {
        return imagem;
    }

    public void setImagem(String imagem) {
        this.imagem = imagem;
    }

    public Foto getFoto() {
        if(this.foto == null){
            this.setFoto(Foto.getFotoPorId(this.getId()));
        }
        return foto;
    }

    public void setFoto(Foto foto) {
        this.foto = foto;
    }

    public Endereco getEndereco() {
        if(endereco == null){
            try {
                endereco = new Endereco(this);
            } catch (EntidadeNaoEncontrada ex) {
            }
        }
        return endereco;
    }

    public void setEndereco(Endereco endereco) {
        this.endereco = endereco;
    }

    @Override
    public String getThumb() {
        return this.imagem;
    }

    @Override
    public double getLongitude() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getLatitude() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Strings SQL.">
    private static String getSQLBuscarPorId() {
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT * ");
        sql.append(" FROM usuario ");
        sql.append(" WHERE ");
        sql.append(" id = ? ");
        return sql.toString();
    }

    private static String getSQLBuscarPorEmailSenha() {
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT u.*, admin.id ");
        sql.append(" FROM usuario ");
        sql.append(" LEFT JOIN administrador admin ON c.id = admin.id ");
        sql.append(" WHERE ");
        sql.append(" u.email = ? AND ");
        sql.append(" u.senha = ? ");
        return sql.toString();
    }

    private static String getSQLInsercao() {
        StringBuilder sql = new StringBuilder();
        sql.append(" INSERT INTO usuario ( ");
        sql.append(" email, ");
        sql.append(" senha, ");
        sql.append(" nome, ");
        sql.append(" imagem ");
        sql.append(" ) VALUES ( ");
        sql.append(" ?, ");
        sql.append(" ?, ");
        sql.append(" ?,  ");
        sql.append(" ?  ");
        sql.append(" )  ");
        return sql.toString();
    }

    private static String getSQLAtualizacao() {
        StringBuilder sql = new StringBuilder();
        sql.append(" UPDATE usuario SET ");
        sql.append(" email = ?, ");
        sql.append(" senha = ?, ");
        sql.append(" nome = ?, ");
        sql.append(" imagem = ? ");
        sql.append(" WHERE ");
        sql.append(" id = ? ");
        return sql.toString();
    }

    private static String getSQLExclusao() {
        StringBuilder sql = new StringBuilder();
        sql.append(" DELETE FROM usuario ");
        sql.append(" WHERE ");
        sql.append(" id = ? ");
        return sql.toString();
    }
    //</editor-fold>
}
